package com.univocity.trader.strategy;

import com.univocity.trader.candles.*;
import com.univocity.trader.indicators.*;

/**
 * 一个 {@code Indicator} 通常执行计算，根据给定工具的价格运动历史来产生值和/或交易信号。
 *
 * 常见的技术指标实现可以在包 {@link com.univocity.trader.indicators} 中找到。
 *
 * @author uniVocity Software Pty Ltd - dev@univocity.com
 * @see com.univocity.trader.indicators
 * @see Candle
 * @see Signal
 * @see Strategy
 * @see StrategyMonitor
 */
public interface Indicator {

    /**
     * 尝试使用给定的蜡烛修改此指标的内部状态。如果配置为 {@link #recalculateEveryTick(boolean)} 设置为 {@code false}，
     * 则蜡烛只能在 {@link Candle#closeTime} 之间的上一个和当前时间相等或大于由 {@link #getInterval()} 指定的间隔时才考虑。
     * <p>
     * 例如，一个移动平均设置为 2 分钟间隔，接收 1 分钟蜡烛，将以以下方式计算：
     * <p>
     * - 第 1 分钟，candle(1.0) = [0.0]。平均值：0.0（忽略）
     * - 第 2 分钟，candle(1.5) = [1.5]。平均值：1.5
     * - 第 3 分钟，candle(1.2) = [1.5]。平均值：1.5（忽略）
     * - 第 4 分钟，candle(1.3) = [1.5, 1.3]。平均值：1.4
     * <p>
     * 当指标配置为 {@link #recalculateEveryTick(boolean)} 设置为 {@code true} 时，则指标状态将基于在由 {@link #getInterval()} 定义的每个间隔中收集的所有累积值，
     * 以及给定蜡烛状态重新计算：
     * <p>
     * - 第 1 分钟，candle(1.0) = [1.0]。平均值：1.0
     * - 第 2 分钟，candle(1.5) = [1.5]。平均值：1.5
     * - 第 3 分钟，candle(1.2) = [1.5, 1.2]。平均值：1.35
     * - 第 4 分钟，candle(1.3) = [1.5, 1.3]。平均值：1.4
     *
     * @param candle 一个由 {@link com.univocity.trader.Exchange} 返回的最新蜡烛，或符号的交易历史（通常由 {@link com.univocity.trader.simulation.SimulatedExchange} 管理）。
     * @return 如果此指标处理了蜡烛，则返回 {@code true}，否则如果被忽略则返回 {@code false}。
     */
    boolean accumulate(Candle candle);

    /**
     * 返回到目前为止累积的蜡烛数量，这些蜡烛在每个由 {@link #getInterval()} 定义的间隔中被收集。
     * 当 {@link #recalculateEveryTick(boolean)} 设置为 {@code true} 时，中间蜡烛可能已经被处理，不应计入。
     *
     * @return 此指标累积的蜡烛数量。
     */
    long getAccumulationCount();

    /**
     * 返回此指标的值，如果适用。
     *
     * @return 指标的值。
     */
    double getValue();

    /**
     * 返回此指标工作的间隔，例如计算 5 秒蜡烛、1 小时蜡烛等的值。
     *
     * @return 此指标使用的时间间隔，以毫秒为单位。
     */
    long getInterval();

    /**
     * 根据当前指标状态和给定的蜡烛发出信号。通常默认为 {@code NEUTRAL}，因为计算取决于用户。
     * 例如，一个 {@link BollingerBand} 可能在给定蜡烛的收盘价小于 {@link BollingerBand#getLowerBand()} 时返回 {@code BUY}。
     * 用户期望覆盖此方法以确定对他们有意义的信号。
     *
     * @param candle 一个由 {@link com.univocity.trader.Exchange} 返回的最新蜡烛，或符号的交易历史（通常由 {@link com.univocity.trader.simulation.SimulatedExchange} 管理）。
     * @return 如果适用
     */
    Signal getSignal(Candle candle);

    /**
     * 返回一个描述，该描述与由 {@link #getSignal(Candle)} 方法返回的 {@link Signal} 的来源/原因有关。
     *
     * @return 与指标发出的最新信号相关联的描述。
     */
    default String signalDescription() {
        return "";
    }

    /**
     * 使用一个 {@link Aggregator} 初始化此指标，该 {@link Aggregator} 将合并分辨率为指定间隔的蜡烛数据，
     * 该间隔由 {@link #getInterval()} 指定。
     *
     * @param aggregator 将在其他指标实例之间共享和使用聚合器实例。
     */
    default void initialize(Aggregator aggregator) {
        throw new IllegalStateException("方法 initialize(aggregator) 必须在 " + this.getClass().getSimpleName() + " 中实现");
    }

    /**
     * 配置此指标以对每个滴答作出反应，即由给定 {@link Aggregator} 部分处理的蜡烛，
     * 这些蜡烛通过 {@link Aggregator#getPartial()} 返回，其值仍在合并以形成由 {@link #getInterval()} 给定的指定间隔的完整蜡烛。
     * 如果为 {@code false}，则此指标只考虑来自 {@link Aggregator#getFull()} 的蜡烛。
     * <p>
     * 例如，一个设置为 2 分钟间隔的移动平均，接收 1 分钟蜡烛，将以以下方式计算：
     * <p>
     * - 第 1 分钟，candle(1.0) = [0.0]。平均值：0.0（忽略）
     * - 第 2 分钟，candle(1.5) = [1.5]。平均值：1.5（完整）
     * - 第 3 分钟，candle(1.2) = [1.5]。平均值：1.5（忽略）
     * - 第 4 分钟，candle(1.3) = [1.5, 1.3]。平均值：1.4（完整）
     * <p>
     * 当指标配置为 {@link #recalculateEveryTick(boolean)} 设置为 {@code true} 时，则指标状态将基于在由 {@link #getInterval()} 定义的每个间隔中收集的所有累积值，
     * 以及来自 {@link Aggregator#getPartial()} 的给定蜡烛重新计算：
     * <p>
     * - 第 1 分钟，candle(1.0) = [1.0]。平均值：1.0（部分）
     * - 第 2 分钟，candle(1.5) = [1.5]。平均值：1.5（完整）
     * - 第 3 分钟，candle(1.2) = [1.5, 1.2]。平均值：1.35（部分）
     * - 第 4 分钟，candle(1.3) = [1.5, 1.3]。平均值：1.4（完整）
     *
     * @param recalculateEveryTick 标志，指示是否应使用部分蜡烛（即在指标间隔内不完全表示整个价格运动的蜡烛）的值来计算此指标的值/信号
     */
    default void recalculateEveryTick(boolean recalculateEveryTick) {

    }
}
